package version3;

import java.awt.RenderingHints.Key;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.Map.Entry;
import java.util.Random;
import java.util.Set;

public class RandomWalk {
	
	public final static int threshold  = 5;
	private HashMap<Integer, HashMap<Integer, Integer>> npList;
	private HashMap<Integer, HashMap<Integer, Integer>> contextList;
	private HashMap<Integer, ArrayList<Integer>> probability;
	private HashMap<Integer, Integer> reachedNum;
	// private HashMap<Integer, Double> prob;
	private double[] prob;
	private ArrayList<Double> sum;
	public static int numtimes = 10000;

	public RandomWalk() {
		npList = new HashMap<Integer, HashMap<Integer, Integer>>();
		// prob = new HashMap<Integer, Double>();
		contextList = new HashMap<Integer, HashMap<Integer, Integer>>();
		probability = new HashMap<Integer, ArrayList<Integer>>();
		reachedNum = new HashMap<Integer, Integer>();
		prob = new double[99401];
		sum = new ArrayList<Double>();

	}

	/**
	 * @param args
	 */
	public static void main(String[] args) {
		RandomWalk rw = new RandomWalk();
		rw.readNP("matrix1.txt");
		System.out.println("read matrix1 ok");
		rw.readContext("matrix2.txt");
		System.out.println("read matrix2 ok");
		// rw.readProbability("context.txt");
		rw.assignProbability();
		// rw.sumProbability();
		// int numtimes = 10000;

		rw.multiiteration(10000);

	}

	public void multiiteration(int i) {
		for (int j = 0; j < i; j++) {
			walk(6, numtimes);
			if (j % 100 == 0) {
				printReachedTime(j);
			}
		}
	}

	public void printReachedTime(int iteration) {
		Set<Entry<Integer, Integer>> set = reachedNum.entrySet();
		for (Entry<Integer, Integer> e : set) {
			System.out.println(iteration + "\t" + e.getKey() + "\t"
					+ e.getValue());
		}
	}

	public void eliminateNP(int i) {
		Set<Entry<Integer, Integer>> set = reachedNum.entrySet();
		for (Entry<Integer, Integer> e : set) {
			if (e.getKey() < threshold) {
				int np = e.getKey();
				//contextList.remove(np);

				HashMap<Integer, Integer> clist = contextList.get(np);
				for(Iterator<Entry<Integer, Integer>> it = clist.entrySet().iterator(); it.hasNext();){
					Entry<Integer, Integer> e2 = it.next();
					int contextID = e2.getKey();
					
					HashMap<Integer, Integer> np_list = npList.get(contextID);
					np_list.remove(np);
					
				
					
				}
				
				
//				Set<Entry<Integer, HashMap<Integer, Integer>>> set2 = npList
//						.entrySet();
//				for (Entry<Integer, HashMap<Integer, Integer>> e2 : set2) {
//					HashMap<Integer, Integer> map = e2.getValue();
//					if (map.containsKey(np)) {
//						map.remove(np);
//
//					}
//
//					// if(map.isEmpty()){
//					// npList.remove(e2.getKey());
//					// }
//				}
//				for (Entry<Integer, HashMap<Integer, Integer>> e3 : set2) {
//					if (e3.getValue().isEmpty()) {
//						npList.remove(e3.getKey());
//					}
//				}

			}
		}
	}

	public void assignProbability() {
		for (int i = 1; i < 99401; i++) {
			prob[i] = 1.0 / 99400.0;
		}

	}

	public void walk(int noun, int numtimes) {
		for (int i = 0; i < numtimes; i++) {
			// // System.out.println(i);
			// if (i == 100) {
			// //
			// System.out.println("====================================100================================");
			// // outputNP();
			// Set<Integer> keys = reachedNum.keySet();
			// for (int a : keys) {
			// System.out.println(i + "\t" + a + "\t" + reachedNum.get(a));
			// }
			//
			// } else if (i == 1000) {
			// //
			// System.out.println("====================================1000================================");
			// // outputNP();
			// Set<Integer> keys = reachedNum.keySet();
			// for (int a : keys) {
			// System.out.println(i + "\t" + a + "\t" + reachedNum.get(a));
			// }
			//
			// } else if (i == 9999) {
			// //
			// System.out.println("====================================9999================================");
			// // outputNP();
			// Set<Integer> keys = reachedNum.keySet();
			// for (int a : keys) {
			// System.out.println(i + "\t" + a + "\t" + reachedNum.get(a));
			// }
			//
			// }
			int context = chooseContext(noun);
			int np = chooseNP(context);
			saveNPNumber(np);

		}
		updateWeights();
		eliminateNP(5);
	}

	public void outputNP() {
		Set<Integer> keys = reachedNum.keySet();
		ArrayList<Integer> keyarray = new ArrayList<Integer>(keys);

		Collections.sort(keyarray, new RWComparator(reachedNum));
		for (int i = 0; i < 1000; i++) {
			System.out.println(keyarray.get(i) + ": "
					+ reachedNum.get(keyarray.get(i)));
		}
	}

	public void updateWeights() {

		// set all the context's prob to 0;
		// for (Iterator<Entry<Integer, Double>> it =
		// prob.entrySet().iterator(); it.hasNext();) {
		// Entry<Integer, Double> e = it.next();
		// // int c1 = (Integer) e.getKey();
		// e.setValue(0.);
		// }

		for (int i = 1; i < 99401; i++) {
			prob[i] = 0;
		}
		// update
		int sumall = 0;
		for (Iterator<Entry<Integer, Integer>> iter = reachedNum.entrySet()
				.iterator(); iter.hasNext();) {

			Entry<Integer, Integer> entry = iter.next();
			int np = entry.getKey();
			int reachedTimes = entry.getValue();
			HashMap<Integer, Integer> contexts = contextList.get(np);
			if (contexts != null) {
				Set<Integer> contextSet = contexts.keySet();
				for (int c : contextSet) {
					prob[c] += reachedTimes;
					sumall += reachedTimes;
				}
			}

			// for (Iterator<Entry<Integer, Double>> it =
			// prob.entrySet().iterator(); it.hasNext();) {
			//
			// Entry<Integer, Double> e = it.next();
			// //int c = e.getKey();
			// double number = e.getValue();
			//
			// double newNumber = number + reachedTimes;
			// e.setValue(newNumber);
			// }

		}

		for (int i = 0; i < 99401; i++) {
			prob[i] = prob[i] / sumall;
		}

	}

	public void saveNPNumber(int np) {
		if (reachedNum.containsKey(np)) {
			reachedNum.put(np, reachedNum.get(np) + 1);

		} else {
			reachedNum.put(np, 1);
		}
		// System.out.println(reachedNum);
	}

	public int chooseNP(int context) {
		HashMap<Integer, Integer> nps = npList.get(context);

		Set<Integer> npss = nps.keySet();
		ArrayList<Integer> nparray = new ArrayList<Integer>(npss);
		Random r = new Random();
		int rn = r.nextInt(nparray.size());

		return nparray.get(rn);

	}

	public int chooseContext(int np) {
		// ArrayList<Integer> randomProb = probability.get(np);
		// int size = randomProb.size();
		// Random r = new Random();
		// int randomNum = r.nextInt(size);
		// return randomProb.get(randomNum);

		HashMap<Integer, Integer> contextlist = contextList.get(np);
		Set<Integer> cs = contextlist.keySet();
		sum.clear();
		HashMap<Integer, Integer> map = new HashMap<Integer, Integer>();
		double temp = 0;
		int j = 0;
		for (int c : cs) {
			map.put(j, c);
			j++;
			temp += prob[c];
			sum.add(temp);
		}

		Random r = new Random();
		double rd = r.nextDouble() * temp;

		int targetContext = 0;
		for (int i = 0; i < sum.size(); i++) {
			if (sum.get(i) >= rd)
				targetContext = i;
			break;
		}

		return map.get(targetContext);

	}

	// public void readProbability(String filename) {
	//
	// try {
	// // HashMap<Integer, Double> prob = new HashMap<Integer, Double>();
	// BufferedReader br = new BufferedReader(new FileReader(filename));
	// String line;
	//
	// while ((line = br.readLine()) != null) {
	// String[] str = line.split("\\s+");
	// int context = Integer.parseInt(str[0]);
	// double p = Double.parseDouble(str[1]);
	//
	// //
	// // for(int i = 0; i < p * 100; i++){
	// // probability.add(context);
	// // }
	//
	// prob.put(context, p);
	//
	// }
	//
	// // Set<Entry<Integer, HashMap<Integer, Integer>>> entries =
	// // contextList.entrySet();
	//
	// for (Iterator<Entry<Integer, HashMap<Integer, Integer>>> iter =
	// contextList
	// .entrySet().iterator(); iter.hasNext();) {
	//
	// Entry<Integer, HashMap<Integer, Integer>> entry = iter.next();
	// int np = entry.getKey();
	// HashMap<Integer, Integer> contexts = entry.getValue();
	// ArrayList<Integer> randomProb = new ArrayList<Integer>();
	//
	// for (Iterator<Entry<Integer, Integer>> it = contexts.entrySet()
	// .iterator(); it.hasNext();) {
	// Entry<Integer, Integer> e = it.next();
	// int c = e.getKey();
	// Double p = prob.get(c);
	//
	// for (int i = 0; i < p * 100; i++) {
	// randomProb.add(c);
	// }
	//
	// }
	// probability.put(np, randomProb);
	// }
	//
	// } catch (FileNotFoundException e) {
	// // TODO Auto-generated catch block
	// e.printStackTrace();
	// } catch (IOException e) {
	// // TODO Auto-generated catch block
	// e.printStackTrace();
	// }
	// // System.out.println(probability);
	// }

	public void readContext(String filename) {

		try {
			BufferedReader br = new BufferedReader(new FileReader(filename));

			int npNum = 0;
			HashMap<Integer, Integer> context = null;
			String line;

			while ((line = br.readLine()) != null) {
				String[] str = line.split("\\s+");
				int npNumber = Integer.parseInt(str[0]);

				if (npNumber != npNum) {
					contextList.put(npNum, context);
					context = new HashMap<Integer, Integer>();
					npNum = npNumber;
				}

				context.put(Integer.parseInt(str[1]), Integer.parseInt(str[2]));

			}
			br.close();
			contextList.remove(0);
		} catch (FileNotFoundException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (NumberFormatException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}

		// System.out.println(contextList);

	}

	public void readNP(String filename) {

		try {
			BufferedReader br = new BufferedReader(new FileReader(filename));
			String line;
			int contextNum = 0;
			HashMap<Integer, Integer> np = null;
			while ((line = br.readLine()) != null) {

				String[] str = line.split("\\s+");

				// System.out.println(str[0]);
				int c = Integer.parseInt(str[1]);
				// System.out.println(c);
				if (c != contextNum) {
					npList.put(contextNum, np);
					np = new HashMap<Integer, Integer>();
					contextNum = c;
				}

				np.put(Integer.parseInt(str[0]), Integer.parseInt(str[2]));

			}
			br.close();
			npList.remove(0);

		} catch (FileNotFoundException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}

		// System.out.println(npList);
	}

}
